package com.example.consumer.service;

import com.example.common.Board;
import com.example.common.Constant;
import com.example.common.RandomUtils;
import com.example.common.Sudoku;
import com.example.consumer.Solve;
import com.example.consumer.SpringConfig;
import com.example.consumer.TooManyResultsException;
import com.example.consumer.dao.SudokuMapper;
import com.example.consumer.service.strategy.ColumnStrategy;
import com.example.consumer.service.strategy.RowStrategy;
import com.example.consumer.service.strategy.SquareStrategy;
import com.example.consumer.service.strategy.Strategy;
import com.rabbitmq.client.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Service
public class MyRabbitListener {
    private static final Logger logger = LoggerFactory.getLogger(MyRabbitListener.class);
    private static final int MAX_INITIAL_NUMBER = Constant.MAX_INITIAL_NUMBER;

    private static final Strategy[] strategy = new Strategy[]{
            new RowStrategy(),
            new ColumnStrategy(),
            new SquareStrategy()
    };

    @Autowired
    private SudokuMapper sudokuMapper;

    @RabbitListener(queues = {SpringConfig.WORK_QUEUE})
    public void listen(char[][] boardCharArray, Channel channel, Message message) throws IOException {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        Board board = new Board(boardCharArray);
        Solve solve = new Solve();
        List<char[][]> allResult = null;
        try {
            allResult = solve.getAllResult(boardCharArray);
            if (!allResult.isEmpty()) {
                //System.out.println("初始题目所有解个数：" + allResult.size());
                String s = find(board, allResult);
                sudokuMapper.insertBoard(new Sudoku(s));
            }
            channel.basicAck(deliveryTag, true);
        } catch (TooManyResultsException e) {
            System.out.println("--------TooManyResultsException----------");
            channel.basicNack(deliveryTag, false, false);
        }
    }

    /**
     * 寻找有唯一解的题目
     * @param board
     * @param allResult 终局的所有可能的解
     */
    private String find(Board board, List<char[][]> allResult) {
        if (board.getNumberCount() > MAX_INITIAL_NUMBER) {
            return "";
        } else if (allResult.size() == 1) {
            logger.info("board:{}", board.toString());
            return board.join();
        }
        Strategy strategy1 = strategy[RandomUtils.getRandomInt(strategy.length)];
        int[] arr = strategy1.insertOneNumber(board, allResult);
        int x1 = arr[0], y1 = arr[1];
        char newNumber = (char)(arr[2] + '1');
        List<char[][]> list2 = new ArrayList<>();
        for (char[][] result1 : allResult) {
            if (result1[x1][y1] == newNumber) {
                list2.add(result1);
            }
        }
        allResult = null;
        return find(board, list2);
    }
}
